package com.didd.core.sensitive.config;

import com.didd.core.common.utils.SpringProxyUtils;
import com.didd.core.sensitive.annotation.ReturnNeedSensitive;
import com.didd.core.sensitive.core.SensitiveProcessor;
import org.aopalliance.intercept.MethodInterceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.TargetSource;
import org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;

/**
 * 〈功能概述〉<br>
 *
 * @author diddd
 * @date: 2021/7/28 18:32
 */
public class EntitySensitiveScanner extends AbstractAutoProxyCreator
        implements InitializingBean, ApplicationContextAware, DisposableBean {

    private static final Logger log = LoggerFactory.getLogger(EntitySensitiveScanner.class);

    private static final Set<String> PROXYED_SET = new HashSet<>();
    private MethodInterceptor interceptor;

    //@Autowired(required = false)
    //private IStrategy iStrategy;

    @Override
    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        try {
            synchronized (PROXYED_SET) {
                if (PROXYED_SET.contains(beanName)) {
                    return bean;
                }
                Class<?> serviceInterface = SpringProxyUtils.findTargetClass(bean);
                Class<?>[] interfacesIfJdk = SpringProxyUtils.findInterfaces(bean);
                if (!existsAnnotation(new Class[]{serviceInterface})
                        && !existsAnnotation(interfacesIfJdk)) {
                    return bean;
                }

                //if (iStrategy == null) {
                //    log.warn("当前服务未定实现类，无法使用实体类脱敏");
                //    return bean;
                //}
                interceptor = new EntitySensitiveInterceptor(new SensitiveProcessor());

                bean = super.wrapIfNecessary(bean, beanName, cacheKey);

                PROXYED_SET.add(beanName);
                return bean;
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

    @Override
    protected Object[] getAdvicesAndAdvisorsForBean(Class beanClass, String beanName, TargetSource customTargetSource)
            throws BeansException {
        return new Object[]{interceptor};
    }

    @Override
    public void destroy() throws Exception {

    }

    @Override
    public void afterPropertiesSet() throws Exception {

    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {

    }

    private boolean existsAnnotation(Class<?>[] classes) {
        if (classes != null && classes.length > 0) {
            for (Class<?> clazz : classes) {
                if (clazz == null) {
                    continue;
                }
                Method[] methods = clazz.getMethods();
                for (Method method : methods) {
                    if (method.getAnnotation(ReturnNeedSensitive.class) != null) {
                        return true;
                    }
                }
            }
        }
        return false;
    }
}
